package com.restkeeper.store.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.restkeeper.exception.BussinessException;
import com.restkeeper.lock.CalculationBusinessLock;
import com.restkeeper.store.entity.SellCalculation;
import com.restkeeper.store.mapper.SellCalculationMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 沽清 服务实现类
 * </p>
 */
@Component
@Service(version = "1.0.0",protocol = "dubbo")
public class SellCalculationServiceImpl extends ServiceImpl<SellCalculationMapper, SellCalculation> implements ISellCalculationService {

    @Autowired
    private CalculationBusinessLock lock;

    @Override
    public Integer getRemainderCount(String dishId) {
        QueryWrapper<SellCalculation> qw = new QueryWrapper<>();
        qw.lambda()
                .select(SellCalculation::getRemainder)
                .eq(SellCalculation::getDishId,dishId);
        SellCalculation sellCalculation = this.getOne(qw);
        if(sellCalculation==null){
            //-1代表不限制份数
            return -1;
        }
        return sellCalculation.getRemainder();
    }

    @Override
    public void add(String dishId,Integer count) {
        QueryWrapper<SellCalculation> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(SellCalculation::getDishId,dishId);
        SellCalculation sellCalculation = this.getOne(qw);
        if(sellCalculation != null) {
            sellCalculation.setRemainder(sellCalculation.getRemainder() + count);
            this.updateById(sellCalculation);
        }
    }

    @Override
    public void decrease(String dishId,Integer count) {
        QueryWrapper<SellCalculation> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(SellCalculation::getDishId,dishId);
        SellCalculation sellCalculation = this.getOne(qw);
        if(sellCalculation != null) {
            int resultCount = sellCalculation.getRemainder()-count;
            if(resultCount<0)resultCount = 0;
            sellCalculation.setRemainder(resultCount);
            this.updateById(sellCalculation);
        }
    }

    /**
     * 加菜时候 沽清剩余数目-1
     * @param dishId
     * @return
     */
    @Override
    public boolean plusDish(String dishId) {
        Integer remainder = getRemainderCount(dishId);
        //没有设置沽清，可以直接添加菜品
        if(remainder <= 0){
            return true;
        }
        String redisKey = dishId;
        //竞争当前菜品id 直到剩余份数为0
        //每次读取最新值
        boolean lockSuccess =lock.spinLock(redisKey,()->getRemainderCount(dishId));
        //竞争失败，意味当前剩余沽清为0
        if(!lockSuccess) throw new BussinessException("当前已沽清");
        //如果竞争成功，沽清剩余数目-1
        if(lockSuccess){
            try {
                QueryWrapper<SellCalculation> qw = new QueryWrapper<>();
                qw.lambda().eq(SellCalculation::getDishId, dishId);
                SellCalculation sellCalculation = this.getOne(qw);
                sellCalculation.setRemainder(sellCalculation.getRemainder() - 1);
                this.updateById(sellCalculation);
            }finally {
                //最后释放锁
                lock.unlock(redisKey);
            }
        }
        return true;
    }

    /**
     * 减菜时候 沽清剩余数目+1
     * @param dishId
     * @return
     */
    @Override
    public boolean reduceDish(String dishId) {
        Integer remainder = getRemainderCount(dishId);
        //没有设置沽清，可以直接减菜
        if(remainder < 0){
            return true;
        }
        QueryWrapper<SellCalculation> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(SellCalculation::getDishId,dishId);
        SellCalculation sellCalculation = this.getOne(qw);
        remainder = sellCalculation.getRemainder()+1;
        //防止超过最大值
        if(remainder>sellCalculation.getSellLimitTotal()){
            remainder=sellCalculation.getSellLimitTotal();
        }
        sellCalculation.setRemainder(remainder);
        return this.updateById(sellCalculation);
    }

}

